home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / Talking KeyBoard / Source / adb.c < prev    next >
Encoding:
Text File  |  1998-06-17  |  8.2 KB  |  325 lines  |  [TEXT/CWIE]

  1. // Program Author: Paul Baxter
  2. //    pbaxter@assistivetech.com
  3. //
  4. //
  5. // Sorry about all the 68k assembler code :-/
  6. //    .....But the ADB Manager is fried
  7.  
  8. #include <DeskBus.h>
  9. #include <Speech.h>
  10. #include <LowMem.h>
  11. #include <Retrace.h>
  12.  
  13. #include "adb.h"
  14. #include "speech.h"
  15. #include "pref.h"
  16. #include "globals.h"
  17. #include "DeferredTask.h"
  18.  
  19. #if GENERATING68K
  20. asm void ADBServiceWrapper(void);
  21. #if !TARGET_RT_MAC_CFM
  22. asm void CallADBServiceRoutineProc(ADBServiceRoutineUPP serviceRoutinePtr, Ptr buffer,
  23.             TempADBServiceRoutineUPP completionProc, long refCon, long command);
  24.  
  25. asm void MyADBInitProcGlue(SInt8 callOrder:__D0);
  26.  
  27. #endif
  28. #endif
  29.  
  30. extern    ADBInitUPP     JADBProc    : 0x06B8;        // where is this defined??
  31.  
  32. static ADBInitUPP    gOldADBInitProc = nil;
  33. static ADBDataBlock gKeyBoardADBData = { 0, 0, 0, 0 };
  34.  
  35. #define kShiftCode 0x38
  36.  
  37. // * ****************************************************************************** *
  38. // *    ADBKeyBoardServiceRoutine
  39. // *
  40. // *            By using this we are guaranteed not to miss any keystrokes
  41. // *
  42. // *            This routine is called at interupt time and may not move memory!
  43. // *            We can not call SpeakText here
  44. // *            Do not use Debug() here!!! You can not use the keyboard!
  45. // * ****************************************************************************** *
  46. pascal void ADBKeyBoardServiceRoutine(Ptr buffer, TempADBServiceRoutineUPP completionProc, long refCon, long command)
  47. {
  48.     ADBServiceRoutineUPP service;
  49.     short count;
  50.     unsigned char ch, state;
  51.  
  52.     // get our globals
  53.     EnterAppCallBack();
  54.  
  55.     // make a local copy of service routine pointer
  56.     service = gKeyBoardADBData.dbServiceRtPtr;
  57.  
  58.     // buffer[0] = length -- always 2 for the keyboard
  59.     // buffer[1] = -1 no data or  hi bit set for up  the rest is the key code
  60.     // buffer[2] = -1 no data or  hi bit set for up  the rest is the key code
  61.  
  62.  
  63.     for (count = 1; count <= buffer[0]; count++) {
  64.         if ((buffer[count] != -1)) {    // -1 means there is no char available
  65.  
  66.             state = buffer[count] & kDepressedMask;
  67.             ch = buffer[count] & kKeyCodeMask;
  68.  
  69.             if (ch == kShiftCode)        // check state of shift key
  70.                 gShiftState = state == kDownState;
  71.  
  72.             if (state == kDownState) {
  73.                 AppendCharBuffer(ch);    // save the char
  74.             }
  75.             // Power key gets sent twice
  76.             if (ch == kPowerKey)
  77.                 break;
  78.         }
  79.     }
  80.  
  81.     InstallDeferredTask();
  82.     // call the original handler so the keyboard still functions
  83.     if (service)
  84.         CallADBServiceRoutineProc(service, buffer, completionProc, refCon, command);
  85.  
  86.     // restore a5
  87.     ExitAppCallBack();
  88. }
  89.  
  90. // * ****************************************************************************** *
  91. // *    InstallADBServiceRoutine
  92. // *                            Install our keyboard ADBHandler
  93. // * ****************************************************************************** *
  94. OSErr InstallADBServiceRoutine(ADBAddress adbaddr)
  95. {
  96.     ADBSetInfoBlock adbsetinfo;
  97.     OSErr err;
  98.  
  99.     err = noErr;
  100.     if ((**gPrefs).speakChars) {
  101.         err = GetADBInfo(&gKeyBoardADBData, adbaddr);
  102.         if (!err) {
  103.             adbsetinfo.siService = gKeyBoardServiceRoutine;
  104.             adbsetinfo.siDataAreaAddr = gKeyBoardADBData.dbDataAreaAddr;
  105.             err = SetADBInfo(&adbsetinfo, adbaddr);
  106.         }
  107.     }
  108.     return err;
  109. }
  110.  
  111. // * ****************************************************************************** *
  112. // *    RemoveADBServiceRoutine
  113. // *                Restore the original keyboard ADBhandler
  114. // * ****************************************************************************** *
  115. void RemoveADBServiceRoutine(ADBAddress adbaddr)
  116. {
  117.     ADBSetInfoBlock adbsetinfo;
  118.     OSErr err;
  119.  
  120.     if (gKeyBoardADBData.dbServiceRtPtr) {
  121.  
  122.         adbsetinfo.siService = gKeyBoardADBData.dbServiceRtPtr;
  123.         adbsetinfo.siDataAreaAddr = gKeyBoardADBData.dbDataAreaAddr;
  124.         err = SetADBInfo(&adbsetinfo, adbaddr);
  125.     }
  126. }
  127.  
  128. // * ****************************************************************************** *
  129. // *    MyADBInitProc
  130. // *            needed to re-install our service routine
  131. // * ****************************************************************************** *
  132. pascal void MyADBInitProc(short callOrder)
  133. {
  134.     OSErr err;
  135.  
  136.     // get our globals
  137.     EnterAppCallBack();
  138.  
  139.     CallADBInitProc(gOldADBInitProc, callOrder);
  140.     if (callOrder != 0) {
  141.         err = InstallADBServiceRoutine(gKeyBoardADBAddress);
  142.     }
  143.  
  144.     // restore a5
  145.     ExitAppCallBack();
  146. }
  147.  
  148. // * ****************************************************************************** *
  149. // *    InstallJADBProc
  150. // *            Install a JADBProc callback for before and after ADBReInit
  151. // * ****************************************************************************** *
  152. void InstallJADBProc(void)
  153. {
  154.     ADBInitUPP ourADBInitProc;
  155.     THz theZone;
  156.     
  157.     theZone = GetZone();
  158.     SetZone(SystemZone());
  159.     gOldADBInitProc = JADBProc;
  160. #if GENERATING68K
  161.     ourADBInitProc = (ADBInitUPP) MyADBInitProcGlue;
  162. #else
  163.     ourADBInitProc = NewADBInitProc(MyADBInitProc);
  164. #endif
  165.     SetZone(theZone);
  166.     JADBProc = ourADBInitProc;
  167. }
  168.  
  169. // * ****************************************************************************** *
  170. // *    UInstallJADBProc
  171. // *            Remove JADBProc
  172. // * ****************************************************************************** *
  173. void UnInstallJADBProc(void)
  174. {
  175.     if (gOldADBInitProc)
  176.         JADBProc = gOldADBInitProc;
  177. }
  178.  
  179. // * ****************************************************************************** *
  180. // *    InitADBService
  181. // *        Init the ADBServieRoutine for the keyboard
  182. // * ****************************************************************************** *
  183. void InitADBService(void)
  184. {
  185.     THz theZone;
  186.  
  187.     theZone = GetZone();
  188.     SetZone(SystemZone());
  189.     // allocate adbservice routine
  190. #if GENERATING68K
  191.     if (!gKeyBoardServiceRoutine)
  192.         gKeyBoardServiceRoutine = NewADBServiceRoutineProc(ADBServiceWrapper);
  193. #else
  194.     if (!gKeyBoardServiceRoutine)
  195.         gKeyBoardServiceRoutine = NewADBServiceRoutineProc(ADBKeyBoardServiceRoutine);
  196. #endif
  197.     if (!gOldADBInitProc)
  198.         gOldADBInitProc = JADBProc;
  199.  
  200.     SetZone(theZone);
  201. }
  202.  
  203. // * ****************************************************************************** *
  204. // *    InitADBAddress
  205. // *        Init the original keyboard address MUST BE CALLED FIRST
  206. // * ****************************************************************************** *
  207. Boolean InitADBAddress(void)
  208. {
  209.     ADBDataBlock adbinfo;
  210.     ADBAddress addr;
  211.     short  adbcount, adbindex;
  212.     
  213.     // see if we can find the keyboard ADBaddress
  214.     adbcount = CountADBs();
  215.     for (adbindex = 1; adbindex <= adbcount; adbindex++) {
  216.         addr = GetIndADB(&adbinfo, adbindex);
  217.         if (addr >= 0) {
  218.             if (adbinfo.origADBAddr == kKeyBoardAddr) {
  219.                 gKeyBoardADBAddress = addr;
  220.                 return true;
  221.             }
  222.         }
  223.     }
  224.     return false;
  225. }
  226.  
  227. // * ****************************************************************************** *
  228. // *    ADBServiceWrapper
  229. // *        Wrapper for 68K ServiceRoutine .. Just call the C version
  230. // * ****************************************************************************** *
  231. #if GENERATING68K
  232. asm void ADBServiceWrapper(void)
  233. {
  234.     fralloc
  235.  
  236. //    This bombs if we set A5 
  237. //     why ????
  238.  
  239. //    AsmEnterAppCallBack
  240.  
  241.     move.l    A0,-(sp)
  242.     move.l    A1,-(sp)
  243.     move.l    A2,-(sp)
  244.     move.l    D0,-(sp)
  245.     jsr        ADBKeyBoardServiceRoutine
  246.     add.l    #16,SP
  247.  
  248. //    AsmExitAppCallBack
  249.  
  250.     frfree
  251.  
  252.     rts
  253. }
  254.  
  255. // * ****************************************************************************** *
  256. // *    CallADBServiceRoutineProc
  257. // *        Why this isn't in a glue lib is beyond me.
  258. // * ****************************************************************************** *
  259. #if !TARGET_RT_MAC_CFM
  260. asm void CallADBServiceRoutineProc(ADBServiceRoutineUPP serviceRoutinePtr, Ptr buffer,
  261.             TempADBServiceRoutineUPP completionProc, long refCon, long command)
  262. {    
  263.  
  264.     fralloc
  265.  
  266.     AsmEnterAppCallBack
  267.  
  268.     movem.l    A0-A3/D0-D3, -(SP)
  269.  
  270.     movea.l    buffer, A0
  271.     movea.l    completionProc, A1
  272.     movea.l    refCon, A2
  273.     move.l    command, D0    
  274.  
  275.     // very strange bug
  276.     //
  277.     // jsr serviceRoutinePtr
  278.     //
  279.     // causes a crash
  280.     // we must put it into an address register
  281.     // and then jsr to it
  282.     movea.l    serviceRoutinePtr, A3
  283.     jsr        (A3)
  284.  
  285.     movem.l    (SP)+,A0-A3/D0-D3
  286.  
  287.     AsmExitAppCallBack
  288.  
  289.     frfree
  290.  
  291.     rts
  292. }
  293.  
  294. // * ****************************************************************************** *
  295. // *    MyADBInitProcGlue
  296. // *        This also should be a glue routine
  297. // * ****************************************************************************** *
  298. asm void MyADBInitProcGlue(SInt8 callOrder:__D0)
  299. {
  300.     AsmEnterAppCallBack
  301.  
  302.     movem.l    d0,-(sp)
  303.     move.l    gOldADBInitProc,a0
  304.     jsr        (a0)
  305.     movem.l    (sp)+,d0
  306.  
  307.     tst.b    d0
  308.     beq.s    @done
  309.  
  310.     clr.w    -(sp)
  311.     move.w    gKeyBoardADBAddress,-(sp)
  312.     jsr     InstallADBServiceRoutine
  313.     move.w    (sp)+,d0
  314.     addq.l    #2,sp
  315.  
  316. @done:
  317.  
  318.     AsmExitAppCallBack
  319.  
  320.     rts
  321. }
  322.  
  323. #endif
  324. #endif
  325.